Cycles in Blender

0x1 Blender简介

Blender是一款开源的跨平台全能三维动画制作软件,提供从建模、动画、材质、渲染、到音频处理、视频剪辑等一系列动画短片制作解决方案。Blender的代码大体架构如下。

如图所示,Blender内置了基于物理渲染的光线追踪渲染器Cycles, Cycles除了实现CPU处理以外,还提供了OpenCL和CUDA的GPU加速,可以大幅度提升渲染速度。
Cycles具有如下特点。Pach-Tracer渲染算法,多核CPU加速渲染,CUDA和OpenCL的GPU渲染支持,多GPU支持,CPU与GPU 混合加速渲染内核。

除了Cycles以外,Blender从2.8版本开始还提供了EEVEE渲染引擎,EEVEE同样是基于物理渲染的光线追踪渲染器,其目标是提升渲染速度,因为目前Cycles的渲染速度还是比较慢的。
本文会对Blender中Cycles的执行流程做进行分析,后续也会对EEVEE的执行流程做介绍。

0x2 Cycles中的线程模型

Cycles中的线程模型如下所示。

Cycles启动以后会创建Session线程,Session会创建一个线程池,这个线程池中的线程数量是cpu的核数。只要有需要并行处理的任务就push到线程池中的queue中,然后空闲线程从queue中取得需要处理的任务并执行。
上图中左边的线程是Session线程,中间的线程TaskScheduler是线程池中其中一个线程的执行过程,线程池中其他线程的执行流程类似。
上图最右边最上边的框中列出了创建线程池中线程的代码。中间的框列出了线程池中的空闲线程从队列中取出任务的过程。下面的框列出了如何把任务push到线程池的代码,注意这些push操作可以在Session中执行,也可以在线程池中的线程运行过程中执行。

0x3 创建Session

创建Session的流程图如下所示。

这个过程主要是构建Scene Graph的过程,Scene Graph的结构体定义如下,其中可以看到需要渲染的数据都保存在这个结构体中,包括Camera,Film,Shader,Mesh,Light,Integrator等。

其中的sync_data过程可以理解成把数据从Blender的上层模块设置到Cycles渲染器中。这样Cycles执行光线跟踪的时候就可以用到这些设置。

数据设置好了以后就可以开始render过程,这个过程是采用光线跟踪的方式渲染出图像。
这个过程中需要关注的是ShaderManager, ShaderManager管理着ShaderGraph,ShaderGraph管理着Node,并且把多个Node连接起来,组成特定操作的Pipeline.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Scene {
public:
/* Optional name. Is used for logging and reporting. */
string name;
/* data */
Camera *camera;
Camera *dicing_camera;
LookupTables *lookup_tables;
Film *film;
Background *background;
Integrator *integrator;
/* data lists */
vector<Object *> objects;
vector<Mesh *> meshes;
vector<Shader *> shaders;
vector<Light *> lights;
vector<ParticleSystem *> particle_systems;
/* data managers */
ImageManager *image_manager;
LightManager *light_manager;
ShaderManager *shader_manager;
MeshManager *mesh_manager;
ObjectManager *object_manager;
ParticleSystemManager *particle_system_manager;
CurveSystemManager *curve_system_manager;
BakeManager *bake_manager;
/* default shaders */
Shader *default_surface;
Shader *default_light;
Shader *default_background;
Shader *default_empty;
/* device */
Device *device;
DeviceScene dscene;
/* parameters */
SceneParams params;
/* mutex must be locked manually by callers */
thread_mutex mutex;
......
};

0x4 光线跟踪的执行

光线跟踪的执行流程如下所示。

这个过程是一个典型的光线跟踪渲染过程,先构建BVH结构体用于后续的加速,然后把一幅图像划分成tile的形式进行渲染,每个线程只处理一个tile,当然每一个位置还需要根据设置的sample的数量进行多次处理,最后根据多次处理的结果生成每一个位置对应的最后的像素值。
这里的svm指的是shader virtual machine, svm对shader的执行进行了抽象,把shader中的操作提练成一个个op的形式,通过对op执行的模拟来执行shader,这些op可以理解成是shader的IR(Intermediate Representation).